home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 January: Mac OS SDK / Dev.CD Jan 00 SDK1.toast / Development Kits / Mac OS / Display Manager SDK / Sample Code / Display Changed CWPro3 / displays.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-01-20  |  11.0 KB  |  425 lines  |  [TEXT/CWIE]

  1. /*************************************************************************************
  2. #
  3. #        displays.c
  4. #
  5. #        This segment handles the Display Manager notification and
  6. #        repositions application windows in response.
  7. #
  8. #        Author(s):     Michael Marinkovich
  9. #                    marink@apple.com
  10. #
  11. #        Modification History: 
  12. #
  13. #            1/19/99        ewa     No longer use nil as the "actualSize" param for
  14. #                                AEGetKeyPtr since the AE Mgr uses nil and writes
  15. #                                the value to location zero.                     
  16. #            1/19/99        ewa     update to CWPro3 and universal interfaces                     
  17. #            10/05/96    MWM        Removed the fixed window title bar height and
  18. #                                replaced it with a func that calculates the
  19. #                                proper height.
  20. #            10/12/95    MWM     Initial coding                     
  21. #
  22. #
  23. #        Copyright © 1992-1999 Apple Computer, Inc., All Rights Reserved
  24. #
  25. #
  26. #        You may incorporate this sample code into your applications without
  27. #        restriction, though the sample code has been provided "AS IS" and the
  28. #        responsibility for its operation is 100% yours.  However, what you are
  29. #        not permitted to do is to redistribute the source as "DSC Sample Code"
  30. #        after having made changes. If you're going to re-distribute the source,
  31. #        we require that you make it clear in the source that the code was
  32. #        descended from Apple Sample Code, but that you've made changes.
  33. #
  34. *************************************************************************************/
  35.  
  36. #include <Events.h>
  37. #include <ToolUtils.h>
  38. #include <Gestalt.h>
  39. #include <OSUtils.h>
  40.  
  41.  
  42. #include "App.h"
  43. #include "Proto.h"
  44.  
  45.  
  46. //----------------------------------------------------------------------
  47. //
  48. //    InstallAEDMNotification - tell DM that we want to be notified by AE.
  49. //                      
  50. //                      
  51. //----------------------------------------------------------------------
  52.  
  53. OSErr InstallAEDMNotification(void)
  54. {
  55.     OSErr            err = noErr;
  56.     
  57.     err = AEInstallEventHandler(kCoreEventClass, kAESystemConfigNotice,
  58.                                 NewAEEventHandlerProc(WorldChangedProc),
  59.                                 0L, false);
  60.     return err;
  61.  
  62. }
  63.  
  64.  
  65.  
  66. //----------------------------------------------------------------------
  67. //
  68. //    WorldChangedProc - Display Manager calls this proc when a depth or  
  69. //                       mode change is made. Your application should
  70. //                       handle window repositioning here. 
  71. //----------------------------------------------------------------------
  72.  
  73. pascal OSErr WorldChangedProc(AppleEvent event, AppleEvent reply, long refCon)
  74. {
  75.     OSErr            err = noErr;
  76.  
  77.     err = HandleNotification(&event);
  78.     
  79.     return noErr;
  80.     
  81. }
  82.  
  83.  
  84. //----------------------------------------------------------------------
  85. //
  86. //    HandleNotification - handle the AppleEvent returned by the 
  87. //                           AppleEvent procedure.
  88. //                      
  89. //----------------------------------------------------------------------
  90.  
  91. OSErr HandleNotification(AppleEvent *event)
  92. {
  93.     OSErr                    err = noErr;
  94.     GrafPtr                    oldPort;
  95.     AEDescList                displayList;
  96.     AEDescList                aDisplay;
  97.     AERecord                oldConfig,newConfig;
  98.     AEKeyword                tempWord;
  99.     DisplayIDType            displayID;
  100.     unsigned long            returnType;
  101.     long                    count;
  102.     Rect                    oldRect, newRect;
  103.     Size                    actualSizeUnused;    
  104.     
  105.     GetPort(&oldPort);
  106.  
  107.     // Get a list of the displays from the Display Notice AppleEvent.
  108.     err = AEGetParamDesc(event,kAEDisplayNotice,typeWildCard,&displayList);
  109.     // How many items in the list
  110.     err = AECountItems(&displayList,&count);
  111.     
  112.     while (count > 0)          // Loop through the list.
  113.     {
  114.         err = AEGetNthDesc(&displayList, count, typeWildCard, &tempWord, 
  115.                                     &aDisplay);
  116.         
  117.         // Get the Old Rect.            
  118.         err = AEGetNthDesc(&aDisplay, 1, typeWildCard, &tempWord, 
  119.                            &oldConfig);
  120.         err = AEGetKeyPtr(&oldConfig, keyDeviceRect, typeWildCard, 
  121.                           &returnType, &oldRect, 8, &actualSizeUnused);
  122.         
  123.         // Get the DisplayID so we can get the GDevice later.                
  124.         err = AEGetKeyPtr(&oldConfig, keyDisplayID, typeWildCard, 
  125.                           &returnType, &displayID, 8, &actualSizeUnused);
  126.  
  127.         // Get the New Rect.                
  128.         err = AEGetNthDesc(&aDisplay, 2, typeWildCard, &tempWord, 
  129.                            &newConfig);
  130.         err = AEGetKeyPtr(&newConfig, keyDeviceRect, typeWildCard, 
  131.                           &returnType, &newRect, 8, &actualSizeUnused);
  132.         
  133.         // If the New and Old rects are not the same then we can assume
  134.         // the GDevice has changed and we need to rearrange the windows.
  135.         if (err == noErr && !EqualRect(&newRect, &oldRect))
  136.             HandleDeviceChange(displayID, &newRect);
  137.  
  138.         count--;
  139.         err = AEDisposeDesc(&aDisplay);
  140.         err = AEDisposeDesc(&oldConfig);
  141.         err = AEDisposeDesc(&newConfig);
  142.  
  143.     }
  144.     
  145.     err = AEDisposeDesc(&displayList);
  146.     SetPort(oldPort);
  147.     
  148.     return err;
  149.     
  150. }
  151.  
  152.  
  153. //----------------------------------------------------------------------
  154. //
  155. //    HandleDeviceChange - called when the oldconfig is different from 
  156. //                         newconfig. Will check all windows on effected 
  157. //                           device and move if needed.
  158. //----------------------------------------------------------------------
  159.  
  160. OSErr HandleDeviceChange(DisplayIDType displayID, Rect *newRect)
  161. {
  162.     OSErr            err;
  163.     GDHandle        gd;
  164.     GDHandle        onGD;
  165.     WindowRef        window;
  166.     
  167.     // Get the GDevice from the DisplayID.
  168.     err = DMGetGDeviceByDisplayID((DisplayIDType) displayID, &gd, false);
  169.  
  170.     if (err == noErr && gd != nil) 
  171.     {
  172.         window = LMGetWindowList();
  173.         
  174.         while (nil != window) 
  175.         {
  176.             SetPort(window); 
  177.             // which device holds the greatest portion of the window
  178.             onGD = GetGreatestDevice(window);
  179.             
  180.             // If the window is not 50% or greater on
  181.             // the desired device then pass it up.
  182.             if (onGD == gd) 
  183.             { 
  184.                 if (OutOfBoundsRect(window->portRect, *newRect)) 
  185.                 {
  186.                     MoveInbounds(window, gd, *newRect); 
  187.                     if (OutOfBoundsRect(window->portRect, *newRect)) 
  188.                     {
  189.                         ResizeInbounds(window, gd, *newRect);
  190.                         
  191.                         // If it is one of our document windows then we need
  192.                         // to reset the std state and the scroll bars.
  193.                         if (GetIsAppWindow(window))
  194.                             AdjustScrollbars(window, true);
  195.                     }        
  196.                 }
  197.                 ResetStdState(window);
  198.  
  199.             }    
  200.             window = (WindowRef)(((WindowPeek)window)->nextWindow);
  201.         }
  202.     }
  203.     
  204.     return err;
  205.     
  206. }
  207.  
  208.     
  209. //----------------------------------------------------------------------
  210. //
  211. //    OutOfBoundsRect -  check to see if the window is out of the device
  212. //                       rect.
  213. //                      
  214. //----------------------------------------------------------------------
  215.  
  216. Boolean OutOfBoundsRect(Rect windRect, Rect screenRect)
  217. {
  218.     Boolean        out = false;
  219.     
  220.  
  221.     GlobalToLocal(&TopLeft(screenRect));
  222.     GlobalToLocal(&BotRight(screenRect));
  223.         
  224.     if ((windRect.right > screenRect.right) || (windRect.bottom > screenRect.bottom))
  225.         out = true;
  226.  
  227.     if ((windRect.left < screenRect.left) || (windRect.top < screenRect.top))
  228.         out = true;
  229.         
  230.     return out;
  231.     
  232. }
  233.     
  234.     
  235. //----------------------------------------------------------------------
  236. //
  237. //    MoveInbounds -  Move window on to desired device
  238. //                        
  239. //                      
  240. //----------------------------------------------------------------------
  241.  
  242. void MoveInbounds(WindowRef window, GDHandle gd, Rect screenRect)
  243. {
  244.     Rect        bounds;
  245.     short        hGlobal;
  246.     short        vGlobal;
  247.     
  248.     bounds = window->portRect;
  249.     
  250.     LocalToGlobal(&TopLeft(bounds));
  251.     LocalToGlobal(&BotRight(bounds));
  252.     
  253.     hGlobal = bounds.left;
  254.     vGlobal = bounds.top;
  255.     
  256.     // we want to make the left top a priority so adjust it first
  257.     // as to override the bottom, right movements. This is so we
  258.     // can resize the window later. No need to adjust the top 
  259.     // because the top coordinates don't change.
  260.     
  261.     if (((bounds.right - bounds.left) > (screenRect.right - screenRect.left)) ||
  262.         ((bounds.bottom - bounds.top) > (screenRect.bottom - screenRect.top))) 
  263.     {
  264.         
  265.         // adjust left
  266.         if (bounds.left < screenRect.left)
  267.             hGlobal = screenRect.left + 4;
  268.         
  269.         vGlobal = screenRect.top;
  270.         if (gd == GetMainDevice())
  271.             vGlobal += (GetMBarHeight() + GetWTitleHeight(window));
  272.  
  273.     }    
  274.     else 
  275.     {
  276.         // adjust left
  277.         if (bounds.left < screenRect.left)
  278.             hGlobal = screenRect.left + 4;
  279.  
  280.         if ((bounds.top - 100 < screenRect.top) && (gd == GetMainDevice()))
  281.             vGlobal = screenRect.top + (GetMBarHeight() + GetWTitleHeight(window));
  282.  
  283.         // adjust right
  284.         if (bounds.right > screenRect.right)
  285.             hGlobal = (screenRect.right - (bounds.right - bounds.left)) - 4;
  286.         
  287.         // adjust bottom
  288.         if (bounds.bottom > screenRect.bottom)
  289.             vGlobal = (screenRect.bottom - (bounds.bottom - bounds.top)) - 4;
  290.     }
  291.     
  292.     MoveWindow(window, hGlobal, vGlobal,false);
  293.         
  294. }
  295.     
  296.  
  297. //----------------------------------------------------------------------
  298. //
  299. //    ResizeInbounds -  resize the window to fit in the graphics device
  300. //                        
  301. //                      
  302. //----------------------------------------------------------------------
  303.  
  304. void ResizeInbounds(WindowRef window, GDHandle gd, Rect screenRect)
  305. {
  306.     Rect        windRect;
  307.     short        h;
  308.     short        v;
  309.  
  310.     windRect = window->portRect;
  311.     
  312.     // make the window bounds the size of the gdRect
  313.     // less the fudge factor.
  314.     h = windRect.right - windRect.left;
  315.     v = windRect.bottom - windRect.top;
  316.  
  317.     if (h > screenRect.right - screenRect.left)
  318.         h = (screenRect.right - screenRect.left) - 8;
  319.     
  320.     if (v > screenRect.bottom - screenRect.top) 
  321.     {
  322.         v = (screenRect.bottom - screenRect.top) - 8;
  323.         
  324.         // If we are on the main device then subtract the mBar
  325.         // height. Also subtract the height of the title
  326.         // bar on the window. 
  327.         
  328.         if (gd == GetMainDevice())
  329.             v -= (LMGetMBarHeight() + GetWTitleHeight(window));
  330.     }        
  331.  
  332.         
  333.     SizeWindow(window, h, v, true);
  334.  
  335. }
  336.     
  337.  
  338. //----------------------------------------------------------------------
  339. //
  340. //    GetGreatestDevice - find thw device that holds the greatest area 
  341. //                        of the window.
  342. //                      
  343. //----------------------------------------------------------------------
  344.  
  345. GDHandle GetGreatestDevice(WindowRef window)
  346. {
  347.     GDHandle    gd;
  348.     GDHandle    savedGD;
  349.     Rect        gdRect;
  350.     Rect        foundRect;
  351.     long        size;
  352.     long        greatest = nil;
  353.  
  354.     gd = DMGetFirstScreenDevice(dmOnlyActiveDisplays);
  355.     savedGD = gd;
  356.     
  357.     // Loop through the device list
  358.     while (gd != nil) 
  359.     {    
  360.         gdRect = (**gd).gdRect;
  361.         
  362.         GlobalToLocal(&topLeft(gdRect));
  363.         GlobalToLocal(&botRight(gdRect));
  364.         
  365.         if (SectRect(&window->portRect, &gdRect, &foundRect)) 
  366.         {
  367.             size = ((long)(foundRect.right - foundRect.left) * 
  368.                    (long)(foundRect.bottom - foundRect.top));
  369.             
  370.             if (size > greatest) 
  371.             {
  372.                 greatest = size;
  373.                 savedGD = gd;        // save the greatest device
  374.             }    
  375.         }
  376.         gd = DMGetNextScreenDevice(gd, dmOnlyActiveDisplays);
  377.     }
  378.     
  379.     return savedGD;
  380.     
  381. }
  382.  
  383.  
  384. //----------------------------------------------------------------------
  385. //
  386. //    ResetStdState - since we are now on a different size screen we need
  387. //                    to change the stdState window size so our zooming
  388. //                    will work properly.  
  389. //----------------------------------------------------------------------
  390.  
  391. void ResetStdState(WindowRef window)
  392. {
  393.     Rect        screenRect;
  394.     
  395.     screenRect = window->portRect;
  396.  
  397.     LocalToGlobal(&TopLeft(screenRect));
  398.     LocalToGlobal(&BotRight(screenRect));
  399.     
  400.     SetWindowStandardState(window, &screenRect);
  401.     
  402. }
  403.     
  404.     
  405. //----------------------------------------------------------------------
  406. //
  407. //    GetWTitleHeight - return the height of the titlebar for a given
  408. //                      window. If the window is nil a zero height will
  409. //                        be returned.
  410. //----------------------------------------------------------------------
  411.     
  412. short GetWTitleHeight(WindowRef window)
  413. {
  414.     short            tHeight = 0;
  415.     
  416.     if (nil != window)                
  417.         tHeight = (**((WindowPeek)window)->contRgn).rgnBBox.top - 
  418.                      (**((WindowPeek)window)->strucRgn).rgnBBox.top;
  419.     
  420.     return tHeight;
  421.  
  422. }
  423.     
  424.  
  425.